package au.edu.adelaide.mips_soft_core.board_interface_pc.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import au.edu.adelaide.adept_sdk_java.AdeptSDKJavaLoader;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.Core;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.CoreListener;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.Device;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.Device.BoardMode;
import au.edu.adelaide.mips_soft_core.board_interface_pc.core.DeviceListener;

public class UI extends JFrame implements ActionListener, DeviceListener, CoreListener{

	JComboBox<Device> deviceSelector = new JComboBox<Device>();
	JButton  deviceConnect = new JButton("Connect");
	JButton deviceDisconnect = new JButton("Disconnect");
	JComboBox<Device.BoardMode> modeChanger = new JComboBox<Device.BoardMode>();

	InfoPanel infoPanel = new InfoPanel();
	UploadMemoryPanel uploadMemoryPanel = new UploadMemoryPanel();
	DownloadMemoryPanel downloadMemoryPanel = new DownloadMemoryPanel();
	DebuggerPanel debuggerPanel = new DebuggerPanel();

	LoggerPanel loggerPanel = new LoggerPanel();

	JTabbedPane tabPanel = new JTabbedPane();

	private Device connectedDevice = null;

	public UI(){
		super("Board Interface - PC");
		JPanel topPanel = new JPanel();
		this.add(topPanel, BorderLayout.NORTH);

		JSplitPane splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tabPanel, loggerPanel);

		this.add(splitter, BorderLayout.CENTER);

		tabPanel.addTab("Configuration - Info", new JScrollPane(infoPanel));
		tabPanel.addTab("Upload to Board", this.uploadMemoryPanel);
		tabPanel.addTab("Download from Board", this.downloadMemoryPanel);
		tabPanel.addTab("Debugger", this.debuggerPanel);
		tabPanel.setEnabledAt(0, false);
		tabPanel.setEnabledAt(1, false);
		tabPanel.setEnabledAt(2, false);
		tabPanel.setEnabledAt(3, false);
		modeChanger.setEnabled(false);
		splitter.setDividerLocation(0.7);
		//building top panel
		{
			refreshDeviceList();
			addComponent(topPanel, new JLabel("Device:"), 0, 0);
			addComponent(topPanel, deviceSelector, 1, 0);
			addComponent(topPanel, deviceConnect, 2, 0);
			addComponent(topPanel, deviceDisconnect, 3, 0);
			addComponent(topPanel, new JLabel("Board Mode:"), 4, 0);
			addComponent(topPanel, modeChanger, 5, 0);
		}

		{
			this.modeChanger.addItem(BoardMode.DOWNLOAD_MODE);
			this.modeChanger.addItem(BoardMode.BOARD_MEMORY_VIEWER);
			this.modeChanger.addItem(BoardMode.DEBUGER);
			this.modeChanger.addItem(BoardMode.RUN);
			this.modeChanger.setSelectedItem(BoardMode.DOWNLOAD_MODE);

		}

		this.deviceDisconnect.setEnabled(false);
		this.deviceConnect.addActionListener(this);
		this.deviceDisconnect.addActionListener(this);
		this.modeChanger.addItemListener(new ItemListener(){

			@Override
			public void itemStateChanged(ItemEvent event) {
				if(event.getStateChange() == ItemEvent.SELECTED){
					connectedDevice.changeBoardMode((BoardMode)modeChanger.getSelectedItem());
				}
			}

		});
		Core.getCore().addCoreListener(this);

	}

	public void refreshDeviceList(){
		this.deviceSelector.removeAllItems();
		if(Core.getCore().getNumberOfDevices() == 0){
			this.deviceSelector.addItem(Device.NO_DEVICE);
			return;
		}
		for(int i = 0; i < Core.getCore().getNumberOfDevices(); i++){
			this.deviceSelector.addItem(Core.getCore().getDevice(i));
		}
	}

	private static void addComponent(JPanel panel, JComponent component, int x, int y){
		panel.add(component);
	}

	@Override
	public void actionPerformed(ActionEvent event) {
		if(event.getSource() == this.deviceConnect){
			Device device = (Device)this.deviceSelector.getSelectedItem();
			if(device == null){
				return;
			}else if(device == Device.NO_DEVICE){
				return;
			}
			this.deviceConnect.setEnabled(false);
			device.connect();
		}else if(event.getSource() == this.deviceDisconnect){
			Device device = (Device)this.deviceSelector.getSelectedItem();
			if(device == null){
				return;
			}else if(device == Device.NO_DEVICE){
				return;
			}
			this.deviceDisconnect.setEnabled(false);
			device.disconnect();
		}
	}


	

	@Override
	public void error(String message) {
		// TODO Auto-generated method stub

	}


	@Override
	public void boardDiagnosed() {
		this.tabPanel.setEnabledAt(0, true);
		this.tabPanel.setEnabledAt(1, true);
		this.tabPanel.setEnabledAt(2, true);
		this.tabPanel.setEnabledAt(3, true);
		this.modeChanger.setEnabled(true);
	}
	
	private void boardUnDiagnosed(){
		this.tabPanel.setSelectedIndex(0);
		this.tabPanel.setEnabledAt(0, false);
		this.tabPanel.setEnabledAt(1, false);
		this.tabPanel.setEnabledAt(2, false);
		this.tabPanel.setEnabledAt(3, false);
		this.modeChanger.setEnabled(false);
		this.deviceSelector.setEnabled(true);
	}

	@Override
	public void deviceListChanged() {
		refreshDeviceList();
	}

	@Override
	public void deviceConnected(Device device) {
		device.addDeviceListener(this);
		this.deviceDisconnect.setEnabled(true);
		this.deviceSelector.setEnabled(false);
		this.connectedDevice = device;
	}

	@Override
	public void deviceDisconnected(Device device) {
		device.removeListener(this);
		this.deviceConnect.setEnabled(true);
		boardUnDiagnosed();
		this.connectedDevice = null;
	}

	@Override
	public void modeChanged() {
		// TODO Auto-generated method stub

	}
	
	public static void main(String[] args){
		if(AdeptSDKJavaLoader.loadNative() != AdeptSDKJavaLoader.LIBRARY_LOAD_RESULT.SUCESS){
			JOptionPane.showMessageDialog(null, AdeptSDKJavaLoader.getLastMessage(), "Failed to load native Library", JOptionPane.ERROR_MESSAGE);
			return;
		}
		UI ui = new UI();
		BufferedImage bi;
		try {
			bi = ImageIO.read(UI.class.getResourceAsStream("AdelaideUniLogo.jpg"));
			ui.setIconImage(new ImageIcon(bi).getImage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		ui.setSize(700, 700);
		ui.setVisible(true);
		ui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}



}
